package com.cse587.gae.controller;

import com.cse587.gae.dto.*;
import com.cse587.gae.entities.Country;
import com.cse587.gae.service.CountryService;
import com.cse587.util.InputException;
import com.cse587.util.Util;
import com.google.appengine.api.capabilities.CapabilitiesPb.CapabilityConfig.Status;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Controller
public class CountryController {

	@Autowired
	private CountryService countryService;
	@Autowired
	private Jaxb2Marshaller objectXmlMarshaller;

	private static final String VIEW_ROOT_FOLDER = "country";

	public void setJaxb2Mashaller(Jaxb2Marshaller jaxb2Mashaller) {
		this.objectXmlMarshaller = jaxb2Mashaller;
	}

	@RequestMapping(value = "/country/list", method = RequestMethod.GET)
	public ModelAndView countryList(Model model) {
		List<Country> list = countryService.getAll();
		CountryList countryList = new CountryList();
		for (Country country : list) {
			CountryDto countryDTO = new CountryDto();
			countryDTO.setCapital(country.getCapital());
			countryDTO.setIso3Code(country.getCodeISO3());
			countryDTO.setCountryName(country.getFullName());
			countryDTO.setUncode(String.valueOf(country.getUncode()));
			countryDTO.setMaxLong(country.getMaxLong());
			countryDTO.setMinLong(country.getMinLong());
			countryDTO.setMaxLat(country.getMaxLat());
			countryDTO.setMinLat(country.getMinLat());
			countryList.getCountryList().add(countryDTO);
		}

		ModelAndView mav = new ModelAndView();
		mav.setViewName(VIEW_ROOT_FOLDER + "/list");
		mav.addObject("root", countryList);

		return mav;
	}

	@RequestMapping(value = "/country/delete/{isoCode}", method = RequestMethod.GET)
	public @ResponseBody
	String emptyDatabase(@PathVariable String isoCode) {
		if (isoCode.toLowerCase().equals("all")) {
			countryService.deleteAllCountry();
			return "the big table is emptyed sucessfully";
		} else {
			boolean status = countryService.deleteCountry(isoCode);
			return status ? "delete " + isoCode + " sucessfully!" : isoCode
					+ " don\'t exist";
		}

	}

	@RequestMapping(value = "/country/uncodeAndCapital/{countryName}", method = RequestMethod.GET)
	public ModelAndView getCountryCodeAndCapital(
			@PathVariable String countryName) throws Exception {
		Country country = countryService.getCountryCodeAndCapital(countryName);
		CountryCode codeTdo = new CountryCode();
		if (country != null) {
			codeTdo.setIso3Code(country.getCodeISO3());
			codeTdo.setCountryName(country.getFullName());
			codeTdo.setUncode(String.valueOf(country.getUncode()));
		} else {
			throw new InputException(Util.COUNTRY_NAME_NO_FOUND);
		}
		ModelAndView mav = new ModelAndView();
		mav.setViewName(VIEW_ROOT_FOLDER + "/uncodeAndCapital");
		mav.addObject("country", codeTdo);
		return mav;
	}
	
	@RequestMapping(value = "/country/isBorder", method = RequestMethod.GET)
	public ModelAndView isBorder(@RequestParam("country1") String countryName1, @RequestParam("country2") String countryName2) throws Exception {
		boolean isBorder = countryService.isBorder(countryName1, countryName2);
		IsBorderDTO dto = new IsBorderDTO();
		dto.setBorder(isBorder);
		
		ModelAndView mav = new ModelAndView();
		mav.setViewName(VIEW_ROOT_FOLDER + "/isBorder");
		mav.addObject("result", dto);
		return mav;
	}

	@RequestMapping(value = "/country/findCountryByCoordinates", method = RequestMethod.GET)
	public ModelAndView getCountryByLongAndLat(
			@RequestParam("long") String longtitude,
			@RequestParam("lat") String lat) throws InputException {
		CountryDto countryDTO = new CountryDto();

		if (Util.isNumber(longtitude) && Util.isNumber(lat)) {
			Double longDouble = Double.valueOf(longtitude);
			Double latDouble = Double.valueOf(lat);
			Country country = countryService.getCountryByCoordinates(latDouble,
					longDouble);
			countryDTO.setCapital(country.getCapital());
			countryDTO.setIso3Code(country.getCodeISO3());
			countryDTO.setCountryName(country.getFullName());
			countryDTO.setUncode(String.valueOf(country.getUncode()));
			countryDTO.setMaxLong(country.getMaxLong());
			countryDTO.setMinLong(country.getMinLong());
			countryDTO.setMaxLat(country.getMaxLat());
			countryDTO.setMinLat(country.getMinLat());
		} else {
			throw new InputException(Util.INVALID_INPUT_PARAM);
		}

		ModelAndView mav = new ModelAndView();
		mav.setViewName(VIEW_ROOT_FOLDER + "/findCountryByCoordinates");
		mav.addObject("country", countryDTO);

		return mav;
	}

	@RequestMapping(value = "/country/countryList/{featureName}", method = RequestMethod.GET)
	public ModelAndView getListCounty(@PathVariable String featureName,
			@RequestParam("order") String order) throws InputException {
		List<Country> list = countryService.getCountryListByFeature(
				featureName, order);
		CountryList countryList = new CountryList();
		for (Country country : list) {
			CountryDto countryDTO = new CountryDto();
			countryDTO.setCapital(country.getCapital());
			countryDTO.setIso3Code(country.getCodeISO3());
			countryDTO.setCountryName(country.getFullName());
			countryDTO.setUncode(String.valueOf(country.getUncode()));
			countryDTO.setMaxLong(country.getMaxLong());
			countryDTO.setMinLong(country.getMinLong());
			countryDTO.setMaxLat(country.getMaxLat());
			countryDTO.setMinLat(country.getMinLat());
			countryList.getCountryList().add(countryDTO);
		}

		ModelAndView mav = new ModelAndView();
		mav.setViewName(VIEW_ROOT_FOLDER + "/featureList");
		mav.addObject("root", countryList);

		return mav;
	}

	@RequestMapping(value = "/country/displayMap/{countryName}", method = RequestMethod.GET)
	public ModelAndView getListCounty(@PathVariable String countryName)
			throws Exception {
		Country country = countryService.displayMap(countryName);
		CountryDto countryDTO = new CountryDto();
		if (country == null) {
			throw new InputException(Util.COUNTRY_NAME_NO_FOUND);
		} else {
			countryDTO.setCapital(country.getCapital());
			countryDTO.setIso3Code(country.getCodeISO3());
			countryDTO.setCountryName(country.getFullName());
			countryDTO.setUncode(String.valueOf(country.getUncode()));
			countryDTO.setMaxLong(country.getMaxLong());
			countryDTO.setMinLong(country.getMinLong());
			countryDTO.setMaxLat(country.getMaxLat());
			countryDTO.setMinLat(country.getMinLat());
			countryDTO.setCapitalLat(country.getCapitalLat());
			countryDTO.setCapitalLong(country.getCapitalLong());
		}
		ModelAndView mav = new ModelAndView();
		mav.setViewName(VIEW_ROOT_FOLDER + "/displayMap");
		mav.addObject("country", countryDTO);

		return mav;
	}

	@RequestMapping(value = "/country/searchByCity/{cityName}", method = RequestMethod.GET)
	public ModelAndView listCapitals(@PathVariable String cityName,
			@RequestParam("lat") String lat, @RequestParam("lng") String lng)
			throws NumberFormatException, InputException {
		AccessibleCountryList result = new AccessibleCountryList();
		
		if (Util.isNumber(lng) && Util.isNumber(lat)) {
			result = countryService.searchByCity(cityName,
					Double.valueOf(lat), Double.valueOf(lng));
			
		}else{
			throw new InputException(Util.INVALID_INPUT_PARAM);
		}
		ModelAndView mav = new ModelAndView();
		mav.setViewName(VIEW_ROOT_FOLDER + "/searchByCity");
		mav.addObject("root", result);

		return mav;
	}

	@RequestMapping(value = "/country/classification", method = RequestMethod.GET)
	public ModelAndView listCapitals(@RequestParam("groupNumber") int groupNumber) {
		GroupList list = countryService.classifyByPopulation(groupNumber);
		

		ModelAndView mav = new ModelAndView();
		mav.setViewName(VIEW_ROOT_FOLDER + "/classify");
		mav.addObject("root", list);

		return mav;
	}

}
